`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/27 14:14:06
// Design Name: 
// Module Name: ALU
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////



module ALU(
    input signed[15:0] ACC_in,
    input signed[15:0] BR_in,
    input [7:0] ALU_control,
    input clk,
    input rst_n,
    output reg signed[15:0] ALU_out,//ALU输出
    output reg signed[15:0] MR_out,//乘法高位
    output reg [7:0] FLAG//标志位 FLAG[0]=SF,FLAG[1]=ZF
);
    reg signed[31:0] product_temp;
    reg signed[15:0] alu_result; // 临时变量保存运算结果
    wire add_signal  = ALU_control[0];
    wire sub_signal  = ALU_control[1];
    wire and_signal  = ALU_control[2];
    wire or_signal   = ALU_control[3];
    wire lsh_signal  = ALU_control[4];
    wire rsh_signal  = ALU_control[5];
    wire mul_signal  = ALU_control[6];
    wire not_signal  = ALU_control[7];

    assign add_signal=ALU_control[0];
    assign sub_signal=ALU_control[1];
    assign and_signal=ALU_control[2];
    assign or_signal=ALU_control[3];
    assign lsh_signal=ALU_control[4];
    assign rsh_signal=ALU_control[5];
    assign mul_signal=ALU_control[6];
    assign not_signal=ALU_control[7];

    wire signed[15:0] add_result;
    wire signed[15:0] sub_result;
    wire signed[31:0] mul_result;
    adder adder_inst (
    .A(ACC_in),  // input wire [15 : 0] A
    .B(BR_in),  // input wire [15 : 0] B
    .S(add_result)  // output wire [15 : 0] S
    );
    suber suber_inst (
    .A(ACC_in),  // input wire [15 : 0] A
    .B(BR_in),  // input wire [15 : 0] B
    .S(sub_result)  // output wire [15 : 0] S
    );
    mult mult_inst(
    .CLK(clk),
    .A(ACC_in),  // input wire [15 : 0] A
    .B(BR_in),  // input wire [15 : 0] B
    .P(mul_result)  // output wire [31 : 0] P
    );
    (* use_dsp = "yes" *) // 使用Dsp块
    // 并行计算所有可能的运算结果
    // wire signed[15:0] add_result  = ACC_in + BR_in;
    // wire signed[15:0] sub_result  = ACC_in - BR_in;
    wire signed[15:0] and_result  = ACC_in & BR_in;
    wire signed[15:0] or_result   = ACC_in | BR_in;
    wire signed[15:0] lsh_result  = ACC_in << BR_in[3:0];
    wire signed[15:0] rsh_result  = ACC_in >> BR_in[3:0]; 
    wire signed[15:0] not_result  = ~ACC_in;

    wire [1:0] add_flags  = {(| (ACC_in + BR_in))  == 0,add_result[15]};
    wire [1:0] sub_flags  = {(|(ACC_in - BR_in))  == 0, sub_result[15]};
    wire [1:0] and_flags  = {(|(ACC_in & BR_in))  == 0, and_result[15]};
    wire [1:0] or_flags   = {(|(ACC_in | BR_in))   == 0, or_result[15]};
    wire [1:0] lsh_flags  = {(|(ACC_in << BR_in[3:0]))  == 0, lsh_result[15]};
    wire [1:0] rsh_flags  = {(|(ACC_in >> BR_in[3:0]))  == 0, rsh_result[15]};
    wire [1:0] mul_flags  = {(|mul_result)  == 0, mul_result[31]}; // 全零判断优化
    wire [1:0] not_flags  = {(|(~ACC_in))  == 0, not_result[15]};

    reg [7:0] ALU_control_reg;
     // 选择逻辑（使用组合电路）
    always @(posedge clk) begin
        ALU_control_reg<=ALU_control;
    end

    // 时序逻辑（仅用于寄存输出）
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ALU_out <= 16'h0000;
            MR_out  <= 16'h0000;
            FLAG    <= 8'b0;
        end else begin
        casez(ALU_control_reg)
            8'b???????1 : begin // ADD
            ALU_out <= add_result;
            FLAG[1:0] <= add_flags;
            MR_out <= 16'h0000;
            end
            8'b??????1? : begin // SUB
            ALU_out <= sub_result;
            FLAG[1:0] <= sub_flags;
            MR_out <= 16'h0000;
            end
            8'b?????1?? : begin // AND
            ALU_out <= and_result;
            FLAG[1:0] <= and_flags;
            MR_out <= 16'h0000;
            end
            8'b????1??? : begin // OR
            ALU_out <= or_result;
            FLAG[1:0] <= or_flags;
            MR_out <= 16'h0000;
            end
            8'b???1???? : begin // LSH
            ALU_out <= lsh_result;
            FLAG[1:0] <= lsh_flags;
            MR_out <= 16'h0000;
            end
            8'b??1????? : begin // RSH
            ALU_out <= rsh_result;
            FLAG[1:0] <= rsh_flags;
            MR_out <= 16'h0000;
            end
            8'b?1?????? : begin // MUL
            ALU_out <= mul_result[15:0];
            FLAG[1:0] <= mul_flags;
            MR_out <= mul_result[31:16];
            end
            8'b1??????? : begin // NOT
            ALU_out <= not_result;
            FLAG[1:0] <= not_flags;
            MR_out <= 16'h0000;
            end
        endcase
            // default: begin
            //     ALU_out = 16'h0000;
            //     FLAG = 2'b00;
            //     MR_out = 16'h0000;
            // end
            // FLAG[1:0] <= FLAG[1:0];
            FLAG[7:2] <= 6'b0;   // 保留高位
        end
    end
endmodule
